/***************************************************************************
 *   Copyright (C) 2007 by Alexandre Masselot,,,   *
 *   alex@alex-laptop   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library General Public License as       *
 *   published by the Free Software Foundation; either version 2 of the    *
 *   License, or (at your option) any later version.                       *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifndef COLLECTIONSPECTRUMLCMSMSCOLLECTION_H
#define COLLECTIONSPECTRUMLCMSMSCOLLECTION_H

#ifdef HAVE_BOOST_SERIALIZATION
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/utility.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/base_object.hpp>
#else
#include <vector>	// is included by the serialiser bellow
#endif

#ifdef HAVE_PROTOBUF
#ifdef _MSC_VER
// we don't create DLLs and thus don't need to pay attention to this warning
#pragma warning( disable: 4251 )
#endif
#include "runlcmsms.pb.h"
#endif

#include "spectrumlcmsms.h"
#include "spectrumlcmsmsmassindexanchor.h"
#include "massindex.h"
#include "masscalculator.h"

namespace bol
{

  /**
  	@author Alexandre Masselot,GeneBio,http://www.genebio.com, <alexandre.masselot@gmail.com>
  */
  
  // TODO currenty, SpectrumLcmsmsCollection is a vector of plain simple pointer. When starting to develop matching engine, we should switch to smart pointers, because MS^2 spectra can outlive the RunLcmsms structure if they stay referenced in a match pair (note: the other member of the match pair, the sequence, is already handled with smart pointers)
  class SpectrumLcmsmsCollection: public vector<SpectrumLcmsms*>
  {
    private:
      MassIndex<SpectrumLcmsmsMassIndexAnchor, vector<const SpectrumLcmsmsMassIndexAnchor*>::const_iterator> *m_index;

#ifdef HAVE_BOOST_SERIALIZATION
      // *** BOOST serialisation code ***
      friend class boost::serialization::access; // gives access to serialisator
      template<class Archive> void serialize ( Archive & ar, const unsigned int version ) const
      {
        // base class serialisation
        ar & boost::serialization::make_nvp("SpectrumLcmsms", boost::serialization::base_object<vector<SpectrumLcmsms*> > ( *this ));
        // NOTE we use make_nvp to specify an alternative name, 
        // because the " < > " contained in the "vector<type>" name break XML
        // don't serialise the index, it will be rebuilt after loading
      }
#endif

    public:
      SpectrumLcmsmsCollection();

      ~SpectrumLcmsmsCollection();
      /**
       * only once the spectrum have been read, we can builb an index (min, max and step are taken from the loaded spectrum)
       */
      void buildIndex();

      MassIndex< SpectrumLcmsmsMassIndexAnchor, vector < const SpectrumLcmsmsMassIndexAnchor * > :: const_iterator >* index() const
      {
        return m_index;
      }

  };

#ifdef HAVE_PROTOBUF
  // TODO if we have MS^3 spectra, duplicate the code from SpectrumLcmsCollection

  static inline bool operator<< (protobuf::RunLcmsms& pb, const class SpectrumLcmsmsCollection& b) {
    pb.clear_ms2(); // now there are 0 elements in ms1's protobuf serialiser
    for (vector<SpectrumLcmsms*>::const_iterator i=b.begin(); i != b.end(); i++) {
      *(pb.add_ms2()) << *(*i);
    }
    return true;
  }

  static inline bool operator>> (const protobuf::RunLcmsms& pb, class SpectrumLcmsmsCollection& b) {
    b.resize(pb.ms2_size());
    for (int i = 0; i < pb.ms2_size(); i++) {
      SpectrumLcmsms* col = new SpectrumLcmsms(pb.ms2(i).parent().moz(),0,pb.ms2(i).parent().intensity());
              // constructor sets M/Z and intensity, at allocation time
      pb.ms2(i) >> (*col);
      b[i] = col;
    }
    return true;
  }
#endif

};

#ifdef HAVE_BOOST_SERIALIZATION
#if defined(WIN32) && (BOOST_VERSION < 103600)
// other wise Visual Studio spits error messages
#include <boost/serialization/extended_type_info_typeid.hpp>
#endif
BOOST_CLASS_EXPORT_GUID(bol::SpectrumLcmsmsCollection, "SpectrumLcmsmsCollection") // register GUID
#endif

#endif
